#include "hx711.h"

long Weight_Tare1 = 0,Weight_Tare2 = 0,Weight_Shiwu = 0;
float GapValue1 = 430, GapValue2 = 430;

int can_read_Channel = 1;

//增加联合体，用来写float小数到flash。默认情况flash只能写整数。参考https://www.cnblogs.com/yangguang-it/p/8604904.html
union Gap_Union {
	float f_gap;
	uint32_t i_gap;
};

//****************************************************
//初始化HX711
//****************************************************
void delay_us(uint16_t time)
{    
   uint16_t i=0;  
   while(time--)
   {
      i=1;  //自己定义
      while(i--) ;    
   }
}

void delay_ms(uint16_t time)
{    
   uint16_t i=0;  
   while(time--)
   {
      i=1200;  //自己定义
      while(i--) ;    
   }
}

//uint32_t writeFlashData = 0x55555555;
//uint32_t addr = 0x8007000;


#define UPDATE_FLAG_ADDR 0x0800EC00

#define MAOPI1_ADDR (0x0800EC00 + 0x400)
#define CAL1_ADDR   (0x0800EC00 + 0x400 + 0x400 )
#define MAOPI2_ADDR (0x0800EC00 + 0x400 + 0x400 + 0x400)
#define CAL2_ADDR   (0x0800EC00 + 0x400 + 0x400 + 0x400 + 0x400)


void writeFlash(uint32_t addr, uint32_t data)
{
    HAL_FLASH_Unlock();

    FLASH_EraseInitTypeDef f;
    f.TypeErase = FLASH_TYPEERASE_PAGES;
    f.PageAddress = addr;
    f.NbPages = 1;
    uint32_t PageError = 0;

    HAL_FLASHEx_Erase(&f, &PageError);
    HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr, data);

     HAL_FLASH_Lock();
}

uint32_t ReadFlash(uint32_t addr)
{
  uint32_t data = *(__IO uint32_t*)(addr);
  printf("addr:0x%x, data:0x%x\r\n", addr, data);
	return data;
}
//****************************************************
//获取毛皮重量
//****************************************************
void Get_Tare(int channel)
{
	if (channel == 1) 
	{
		if (ReadFlash(MAOPI1_ADDR) == 0xffffffff) 
		{
			printf("mp1 sensor\n");
			Weight_Tare1 = HX711_Read_By_Channel(channel);
		} else {
			printf("mp1 flash\n");
			Weight_Tare1 = ReadFlash(MAOPI1_ADDR);	
		}
    
	} else if (channel == 2) 
	{
		if (ReadFlash(MAOPI2_ADDR) == 0xffffffff) 
		{
			printf("mp2  sensor\n");
			Weight_Tare2 = HX711_Read_By_Channel(channel);		
		} else 
		{
			printf("mp2 flash\n");
			Weight_Tare2 = ReadFlash(MAOPI2_ADDR);
		}
	}
} 

void Zero_Balance(int channel)
{
	unsigned long Mao_Pi = HX711_Read_By_Channel(channel);	
	if (channel == 1) 
	{
		writeFlash(MAOPI1_ADDR, Mao_Pi);
		Weight_Tare1 = Mao_Pi;
	} else if (channel == 2) 
	{
		writeFlash(MAOPI2_ADDR, Mao_Pi);
		Weight_Tare2 = Mao_Pi;
	}
}

void Get_Cal(int channel)
{
	if (channel == 1) 
	{
		if (ReadFlash(CAL1_ADDR) != 0xffffffff) 
		{
			union Gap_Union cal_union;
			cal_union.i_gap = ReadFlash(CAL1_ADDR);
			GapValue1 = cal_union.f_gap;
			printf("cal%d from flash f_gap=%f\n",channel, GapValue1);
		}
	} else if (channel == 2) 
	{
		if (ReadFlash(CAL2_ADDR) != 0xffffffff)
		{
			union Gap_Union cal_union;
			cal_union.i_gap = ReadFlash(CAL2_ADDR);
			GapValue2 = cal_union.f_gap;
			printf("cal%d from flash f_gap=%f\n",channel , GapValue2);
		}
	}
} 

void Cal_Balance(int channel, int cal_weight)
{
 	unsigned long buffer = HX711_Read_By_Channel(channel);
	if (channel == 1) {
		unsigned long weight = buffer - Weight_Tare1;
		GapValue1 = (float)weight / (float)cal_weight;
		union Gap_Union cal_union;
		cal_union.f_gap = GapValue1;
		printf("Cal_Balance%d f_gap = %f", channel, cal_union.f_gap);
		writeFlash(CAL1_ADDR, cal_union.i_gap);
	} else if (channel == 2) {
		unsigned long weight = buffer - Weight_Tare2;
		GapValue2 = (float)weight / (float)cal_weight;
		union Gap_Union cal_union;
		cal_union.f_gap = GapValue2;
		printf("Cal_Balance%d f_gap = %f", channel, cal_union.f_gap);
		writeFlash(CAL2_ADDR, cal_union.i_gap);
	}
}


unsigned long HX711_Read_By_Channel(int channel)	//增益128
{
	if (can_read_Channel == channel) 
	{
		return HX711_Read_Once();
	} else 
	{
		if (can_read_Channel == 2) 
		{
			HX711_Read_Once(); //skip channle2
			can_read_Channel = 1;
			return HX711_Read_Once();
		} else 
		{
			HX711_Read_Once();
			delay_us(1);
			HAL_GPIO_WritePin(HX711_SCK_PORT,HX711_SCK_PIN ,GPIO_PIN_SET);
			delay_us(2);
			HAL_GPIO_WritePin(HX711_SCK_PORT,HX711_SCK_PIN ,GPIO_PIN_RESET);
		  delay_us(1);
			can_read_Channel = 1;
			return HX711_Read_Once();	
		}
	}
}

unsigned long HX711_Read_Once()	//增益128
{
	unsigned long val; 

  HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN , GPIO_PIN_RESET);//模块没准备好时，单片机在CLK线上输出低电平
  val = 0;
	int retry = 0;
  while(1)
	{
	    if(HAL_GPIO_ReadPin(HX711_DT_PORT, HX711_DT_PIN)==0)
		{
			delay_us(100);
			if(HAL_GPIO_ReadPin(HX711_DT_PORT, HX711_DT_PIN)==0)
			{
				break;
			}			
		}
			
		retry++;
		if(retry >= 1000000)
		{
			break;
		}
	}
	delay_us(1);
  for(int i = 0; i < 24; i++)
	{ 			
		HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN, GPIO_PIN_SET);
		delay_us(1);
	  val = val<<1; 	
		HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN, GPIO_PIN_RESET);		
	  if(HAL_GPIO_ReadPin(HX711_DT_PORT, HX711_DT_PIN) == 1)//读入数据
		{
			val++; 
		}		
			
	} 
	HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN, GPIO_PIN_SET);
	delay_us(2);
	//printf("before count = %0x \n", count);
	//printf("before count long = %lu \n", count);
  val = val^0x800000;//第25个脉冲下降沿来时，转换数据
	HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN, GPIO_PIN_RESET);
	return val;
}


//****************************************************
//平均称重
//****************************************************
long Get_Weight_Average(int channel, int times)
{
  long max_buffer = 0;
	long min_buffer = 0;
  long buffer = 0;
  long buffer_sum = 0;
	long buffer_average = 0;
	if (times < 3)
	{
		printf("error,time must bigger than 3!");
		return -1;
	}
  for (int i = 0; i < times; i++) 
	{
		buffer = HX711_Read_By_Channel(channel);
		if (i == 0) 
		{
			min_buffer = buffer;
			max_buffer = buffer;
		} else 
		{
			if (buffer > max_buffer)
			{
				max_buffer = buffer;
			} else if (buffer < min_buffer)
			{
				min_buffer = buffer;
			}			
		}
		buffer_sum = buffer_sum + buffer;
	}
	buffer_average = (buffer_sum - max_buffer - min_buffer) / (times - 2);
	return Cal_Weight_On_Tare(buffer_average, channel);
}

//****************************************************
//实时称重
//****************************************************
long Get_Weight_immediately(int channel)
{
  long buffer = 0;
	buffer = HX711_Read_By_Channel(channel);
	return Cal_Weight_On_Tare(buffer, channel);
}

//****************************************************
//去皮重
//****************************************************
long Cal_Weight_On_Tare(long buffer, int channel) {
  long actual_weight = 0;
	int gap_value = GapValue1;
	long weight_tare = 0;
	//get gap and tare
	if (channel == 1) 
	{
		gap_value = GapValue1;
		weight_tare = Weight_Tare1;
	} else if (channel == 2) 
	{
		gap_value = GapValue2;
		weight_tare = Weight_Tare2;
	}

	actual_weight = buffer - weight_tare;
	actual_weight = (long)((float)actual_weight/gap_value); 	
	return actual_weight;
}


